package main

import (
    "fmt"
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/gin"
    "github.com/google/uuid"
    "net/http"
    "sync"
    "time"
)

func main() {
    var userData sync.Map
    type UserDataValue struct {
        Passwd string
        Name string
    }
    var sessionData sync.Map
    type SessionDataValue struct {
        Username string
        LoginDate string
    }

    r := gin.Default()

    // 设置 session 的中间件
    store := cookie.NewStore([]byte("fkxxyz-secret"))
    r.Use(sessions.Sessions("fkxxyz-session", store))

    // 注册
    r.GET("/register", func(c *gin.Context) {
        username := c.Query("username")
        passwd := c.Query("passwd")
        name := c.Query("name")
        if len(username) == 0 || len(passwd) == 0 || len(name) == 0 {
            c.String(http.StatusBadRequest, "字段不能为空")
            return
        }
        userData.Store(username, UserDataValue{
            Passwd: passwd,
            Name: name,
        })
        c.Status(http.StatusOK)
    })

    // 登录
    r.GET("/login", func(c *gin.Context) {
        // 验证
        username := c.Query("username")
        passwd := c.Query("passwd")
        v, ok := userData.Load(username)
        if !ok {
            c.String(http.StatusUnauthorized, fmt.Sprintf("用户 %s 不存在", username))
            return
        }
        rightPasswd := v.(UserDataValue).Passwd
        fmt.Println("passwd = ", passwd)
        fmt.Println("rightPasswd = ", rightPasswd)
        if passwd != rightPasswd {
            c.String(http.StatusUnauthorized, fmt.Sprintf("用户 %s 密码不正确", username))
            return
        }

        // 生成 token
        token := uuid.NewString()
        value := SessionDataValue{
            Username: username,
            LoginDate: time.Now().String(),
        }

        // token 存到服务器
        sessionData.Store(token, value)

        // token 发送到 cookie
        session := sessions.Default(c)
        session.Set("token", token)
        err := session.Save()
		if err != nil {
            c.Status(http.StatusInternalServerError)
		}

        c.Status(http.StatusOK)
    })

    // 登出
    r.GET("/logout", func(c *gin.Context) {

    })

    // 访问
    r.GET("/hello", func(c *gin.Context) {
        session := sessions.Default(c)

        // 从 cookie 获取 token
        v := session.Get("token")
        if v == nil {
            c.String(http.StatusUnauthorized, "未登录")
            return
        }
        token := v.(string)

        // 从数据库中查询 token
        v, ok := sessionData.Load(token)
        if !ok {
            c.String(http.StatusUnauthorized, "非法 cookie")
            return
        }
        sessionData := v.(SessionDataValue)

        // 查询用户信息
        v, ok = userData.Load(sessionData.Username)
        if !ok {
            c.String(http.StatusUnauthorized, fmt.Sprintf("不存在的用户 %s", sessionData.Username))
            return
        }
        userData := v.(UserDataValue)

        c.JSON(http.StatusOK, gin.H{
            "username": sessionData.Username,
            "passwd": userData.Passwd,
            "name": userData.Name,
        })
    })

    err := r.Run()
    if err != nil {
        panic(err)
    }
}
